package com.mhr.ai.cr.service

import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.project.Project
import com.mhr.ai.cr.model.ChangeType
import com.mhr.ai.cr.model.FileChange
import com.mhr.ai.cr.model.GitMRInfo
// 移除协程导入
import java.util.regex.Pattern

/**
 * Git MR 服务类
 * 负责解析 MR 链接并获取文件变更信息
 */
@Service(Service.Level.PROJECT)
class GitMRService(private val project: Project) {
    
    private val logger = thisLogger()
    private val httpClient = service<HttpClientService>()
    
    /**
     * 解析 MR 链接并获取变更信息
     */
    fun analyzeMRUrl(mrUrl: String): Result<GitMRInfo> {
        return try {
            logger.info("开始分析 MR 链接: $mrUrl")
            
            // 解析不同平台的 MR 链接
            val mrInfo = when {
                mrUrl.contains("gitlab") -> parseGitLabMR(mrUrl)
                mrUrl.contains("github") -> parseGitHubPR(mrUrl)
                mrUrl.contains("gitee") -> parseGiteeMR(mrUrl)
                else -> throw IllegalArgumentException("不支持的 Git 平台，目前支持 GitLab、GitHub 和 Gitee")
            }
            
            Result.success(mrInfo)
        } catch (e: Exception) {
            logger.error("分析 MR 链接失败", e)
            Result.failure(e)
        }
    }
    
    /**
     * 解析 GitLab MR
     */
    private fun parseGitLabMR(url: String): GitMRInfo {
        // 提取项目信息和 MR ID
        val pattern = Pattern.compile("https?://([^/]+)/([^/]+/[^/]+)/-/merge_requests/(\\d+)")
        val matcher = pattern.matcher(url)
        
        if (!matcher.find()) {
            throw IllegalArgumentException("无效的 GitLab MR 链接格式")
        }
        
        val host = matcher.group(1)
        val projectPath = matcher.group(2)
        val mrId = matcher.group(3)
        
        // 构建 API URL
        val encodedProjectPath = projectPath.replace("/", "%2F")
        val apiUrl = "https://$host/api/v4/projects/$encodedProjectPath/merge_requests/$mrId"
        val changesUrl = "$apiUrl/changes"
        
        try {
            // 由于移除了协程支持，暂时使用模拟数据
            // 实际项目中可以使用同步HTTP客户端或其他方式
            logger.info("尝试获取GitLab MR信息，当前使用模拟数据")
            return createMockMRInfo(mrId, url, "GitLab")
            
            /*
            // 获取 MR 基本信息 (需要协程支持)
            val mrResult = httpClient.getJson(apiUrl)
            val changesResult = httpClient.getJson(changesUrl)
            
            if (mrResult.isFailure || changesResult.isFailure) {
                logger.warn("API 调用失败，使用模拟数据")
                return createMockMRInfo(mrId, url, "GitLab")
            }
            
            val mrData = mrResult.getOrThrow()
            val changesData = changesResult.getOrThrow()
            
            // 解析 MR 信息
            val title = mrData.get("title")?.asString ?: "MR #$mrId"
            val description = mrData.get("description")?.asString ?: ""
            val sourceBranch = mrData.get("source_branch")?.asString ?: "unknown"
            val targetBranch = mrData.get("target_branch")?.asString ?: "unknown"
            val authorName = mrData.getAsJsonObject("author")?.get("name")?.asString ?: "unknown"
            
            // 解析文件变更
            val changes = parseGitLabChanges(changesData)
            
            return GitMRInfo(
                id = mrId,
                title = title,
                description = description,
                sourceBranch = sourceBranch,
                targetBranch = targetBranch,
                author = authorName,
                webUrl = url,
                changes = changes
            )
            */
        } catch (e: Exception) {
            logger.warn("解析 GitLab MR 失败，使用模拟数据: ${e.message}")
            return createMockMRInfo(mrId, url, "GitLab")
        }
    }
    
    /**
     * 解析 GitHub PR
     */
    private fun parseGitHubPR(url: String): GitMRInfo {
        val pattern = Pattern.compile("https?://github.com/([^/]+)/([^/]+)/pull/(\\d+)")
        val matcher = pattern.matcher(url)
        
        if (!matcher.find()) {
            throw IllegalArgumentException("无效的 GitHub PR 链接格式")
        }
        
        val owner = matcher.group(1)
        val repo = matcher.group(2)
        val prNumber = matcher.group(3)
        
        // GitHub API 调用
        val apiUrl = "https://api.github.com/repos/$owner/$repo/pulls/$prNumber"
        val filesUrl = "https://api.github.com/repos/$owner/$repo/pulls/$prNumber/files"
        
        try {
            // 由于移除了协程支持，暂时使用模拟数据
            logger.info("尝试获取GitHub PR信息，当前使用模拟数据")
            return createMockMRInfo(prNumber, url, "GitHub")
            
            /*
            val prResult = httpClient.getJson(apiUrl)
            val filesResult = httpClient.getJson(filesUrl)
            
            if (prResult.isFailure || filesResult.isFailure) {
                logger.warn("GitHub API 调用失败，使用模拟数据")
                return createMockMRInfo(prNumber, url, "GitHub")
            }
            
            val prData = prResult.getOrThrow()
            val filesData = filesResult.getOrThrow()
            
            // 解析 PR 信息
            val title = prData.get("title")?.asString ?: "PR #$prNumber"
            val description = prData.get("body")?.asString ?: ""
            val sourceBranch = prData.getAsJsonObject("head")?.get("ref")?.asString ?: "unknown"
            val targetBranch = prData.getAsJsonObject("base")?.get("ref")?.asString ?: "unknown"
            val authorName = prData.getAsJsonObject("user")?.get("login")?.asString ?: "unknown"
            
            // 解析文件变更
            val changes = parseGitHubFiles(filesData)
            
            return GitMRInfo(
                id = prNumber,
                title = title,
                description = description,
                sourceBranch = sourceBranch,
                targetBranch = targetBranch,
                author = authorName,
                webUrl = url,
                changes = changes
            )
            */
        } catch (e: Exception) {
            logger.warn("解析 GitHub PR 失败，使用模拟数据: ${e.message}")
            return createMockMRInfo(prNumber, url, "GitHub")
        }
    }
    
    /**
     * 解析 Gitee MR
     */
    private fun parseGiteeMR(url: String): GitMRInfo {
        // Gitee 的 MR 链接解析逻辑
        val pattern = Pattern.compile("https?://gitee.com/([^/]+)/([^/]+)/pulls/(\\d+)")
        val matcher = pattern.matcher(url)
        
        if (!matcher.find()) {
            throw IllegalArgumentException("无效的 Gitee MR 链接格式")
        }
        
        val owner = matcher.group(1)
        val repo = matcher.group(2)
        val prNumber = matcher.group(3)
        
        // 模拟数据 (实际需要调用 Gitee API)
        return GitMRInfo(
            id = prNumber,
            title = "Gitee PR #$prNumber",
            description = "Gitee MR 分析",
            sourceBranch = "feature-branch",
            targetBranch = "main",
            author = "developer",
            webUrl = url,
            changes = createMockChanges()
        )
    }
    
    /**
     * 解析 GitLab 文件变更
     */
    private fun parseGitLabChanges(changesData: JsonObject): List<FileChange> {
        return try {
            val changes = changesData.getAsJsonArray("changes")
            changes?.map { changeElement ->
                val change = changeElement.asJsonObject
                val oldPath = change.get("old_path")?.asString
                val newPath = change.get("new_path")?.asString ?: ""
                val diff = change.get("diff")?.asString ?: ""
                
                // 判断变更类型
                val changeType = when {
                    change.get("new_file")?.asBoolean == true -> ChangeType.ADDED
                    change.get("deleted_file")?.asBoolean == true -> ChangeType.DELETED
                    change.get("renamed_file")?.asBoolean == true -> ChangeType.RENAMED
                    else -> ChangeType.MODIFIED
                }
                
                // 计算添加和删除的行数
                val (addedLines, removedLines) = calculateLineChanges(diff)
                
                FileChange(
                    oldPath = oldPath,
                    newPath = newPath,
                    changeType = changeType,
                    diff = diff,
                    addedLines = addedLines,
                    removedLines = removedLines
                )
            } ?: createMockChanges()
        } catch (e: Exception) {
            logger.warn("解析 GitLab 变更失败: ${e.message}")
            createMockChanges()
        }
    }
    
    /**
     * 解析 GitHub 文件变更
     */
    private fun parseGitHubFiles(filesData: JsonObject): List<FileChange> {
        return try {
            // GitHub API 返回的是数组
            val filesArray = if (filesData.isJsonArray) {
                filesData.asJsonArray
            } else {
                // 如果不是数组，可能是包装在某个字段中
                filesData.getAsJsonArray("files") ?: JsonArray()
            }
            
            filesArray.map { fileElement ->
                val file = fileElement.asJsonObject
                val filename = file.get("filename")?.asString ?: ""
                val status = file.get("status")?.asString ?: "modified"
                val patch = file.get("patch")?.asString ?: ""
                val additions = file.get("additions")?.asInt ?: 0
                val deletions = file.get("deletions")?.asInt ?: 0
                val previousFilename = file.get("previous_filename")?.asString
                
                val changeType = when (status) {
                    "added" -> ChangeType.ADDED
                    "removed" -> ChangeType.DELETED
                    "renamed" -> ChangeType.RENAMED
                    else -> ChangeType.MODIFIED
                }
                
                FileChange(
                    oldPath = previousFilename ?: if (changeType != ChangeType.ADDED) filename else null,
                    newPath = filename,
                    changeType = changeType,
                    diff = patch,
                    addedLines = additions,
                    removedLines = deletions
                )
            }
        } catch (e: Exception) {
            logger.warn("解析 GitHub 文件变更失败: ${e.message}")
            createMockChanges()
        }
    }
    
    /**
     * 计算差异中的行数变化
     */
    private fun calculateLineChanges(diff: String): Pair<Int, Int> {
        var addedLines = 0
        var removedLines = 0
        
        diff.lines().forEach { line ->
            when {
                line.startsWith("+") && !line.startsWith("+++") -> addedLines++
                line.startsWith("-") && !line.startsWith("---") -> removedLines++
            }
        }
        
        return Pair(addedLines, removedLines)
    }
    
    /**
     * 创建模拟 MR 信息
     */
    private fun createMockMRInfo(id: String, url: String, platform: String): GitMRInfo {
        return GitMRInfo(
            id = id,
            title = "$platform MR/PR #$id",
            description = "这是一个模拟的 $platform MR/PR 数据。\n\n要获取真实数据，请配置相应的 API 访问权限。",
            sourceBranch = "feature/new-feature",
            targetBranch = "main",
            author = "developer",
            webUrl = url,
            changes = createMockChanges()
        )
    }
    
    /**
     * 创建模拟的文件变更数据
     */
    private fun createMockChanges(): List<FileChange> {
        return listOf(
            FileChange(
                oldPath = "src/main/java/com/example/Service.java",
                newPath = "src/main/java/com/example/Service.java",
                changeType = ChangeType.MODIFIED,
                diff = """
                    @@ -10,7 +10,7 @@ public class Service {
                     
                         public void processData() {
                    -        // 旧的实现
                    +        // 新的实现
                             System.out.println("处理数据");
                         }
                     }
                """.trimIndent(),
                addedLines = 1,
                removedLines = 1
            ),
            FileChange(
                oldPath = null,
                newPath = "src/main/java/com/example/NewFeature.java",
                changeType = ChangeType.ADDED,
                diff = """
                    @@ -0,0 +1,15 @@
                    +package com.example;
                    +
                    +public class NewFeature {
                    +    public void newMethod() {
                    +        System.out.println("新功能");
                    +    }
                    +}
                """.trimIndent(),
                addedLines = 15,
                removedLines = 0
            ),
            FileChange(
                oldPath = "README.md",
                newPath = "README.md",
                changeType = ChangeType.MODIFIED,
                diff = """
                    @@ -1,4 +1,6 @@
                     # 项目说明
                     
                    +## 新增功能
                    +- 添加了新的服务类
                     ## 使用方法
                     请参考文档
                """.trimIndent(),
                addedLines = 2,
                removedLines = 0
            )
        )
    }
}